import re
from collections import Counter, defaultdict
from datetime import datetime, timedelta


class MQTTLogAnalyzer:
    """MQTT日志分析器"""
    
    def __init__(self):
        self.stats = {
            'topic_types': {
                'ntp': Counter(),          # NTP校时
                'shadow': Counter(),       # 影子系统
                'upgrade': Counter(),      # 升级
                'bind': Counter(),         # 绑定状态
                'address': Counter(),      # 地址切换
                'other': Counter()         # 其他消息
            },
            'mqtt_operations': Counter(),  # MQTT操作统计
            'start_time': None,            # 记录第一条日志时间
            'end_time': None               # 记录最后一条日志时间
        }
    
    def _parse_timestamp(self, line):
        """从日志行解析时间戳"""
        timestamp_match = re.search(r'(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d+\+\d{2}:\d{2})', line)
        if timestamp_match:
            try:
                timestamp_str = timestamp_match.group(1)
                dt = datetime.fromisoformat(timestamp_str)
                return dt
            except ValueError as e:
                print(f"时间戳解析错误: {e}")
                return None
        return None
    
    def _is_in_date_range(self, log_time, start_date, end_date):
        """检查日期是否在指定范围内"""
        if not log_time:
            return False
        
        log_date = log_time.date()
        # 结束日期加1天，使其包含当天
        end_date_inclusive = end_date + timedelta(days=1)
        return start_date <= log_date < end_date_inclusive

    def _analyze_topic(self, topic, msg_type, count=1):
        """分析Topic类型"""
        # NTP校时
        if 'ntp' in topic:
            self.stats['topic_types']['ntp'][topic] += count
        # 影子系统
        elif topic.startswith('shadow/'):
            self.stats['topic_types']['shadow'][topic] += count
        # 升级
        elif 'ota' in topic:
            self.stats['topic_types']['upgrade'][topic] += count
        # 绑定状态
        elif 'bind' in topic:
            self.stats['topic_types']['bind'][topic] += count
        # 地址切换
        elif 'mqtt_host_change' in topic:
            self.stats['topic_types']['address'][topic] += count
        # 其他消息
        else:
            self.stats['topic_types']['other'][topic] += count

    def analyze_log(self, log_file, start_date_str=None, end_date_str=None):
        """分析日志文件，可选择指定日期范围"""
        print(f"开始分析日志文件: {log_file}")
        
        # 如果指定了日期范围，则转换为datetime.date对象
        start_date = None
        end_date = None
        if start_date_str and end_date_str:
            print(f"分析时间范围: {start_date_str} 至 {end_date_str}")
            start_date = datetime.strptime(start_date_str, '%Y-%m-%d').date()
            end_date = datetime.strptime(end_date_str, '%Y-%m-%d').date()
        
        with open(log_file, 'r', encoding='utf-8') as f:
            for line in f:
                # 解析时间戳
                timestamp = self._parse_timestamp(line)
                
                # 如果指定了日期范围，检查是否在范围内
                if start_date and end_date and timestamp:
                    if not self._is_in_date_range(timestamp, start_date, end_date):
                        continue
                
                if timestamp:
                    if self.stats['start_time'] is None:
                        self.stats['start_time'] = timestamp
                    self.stats['end_time'] = timestamp

                # 提取MQTT操作类型
                if 'packet:' in line:
                    packet_match = re.search(r'packet: (\w+)', line)
                    if packet_match:
                        operation = packet_match.group(1)
                        # 更新操作计数
                        self.stats['mqtt_operations'].update([operation])

                # Topic统计
                topic_match = re.search(r'Topic=([\w/]+)', line)
                if topic_match:
                    topic = topic_match.group(1)
                    msg_type = 'send' if 'mqtt_packet_sent' in line else 'receive'
                    self._analyze_topic(topic, msg_type)

    def _calculate_frequency(self, count):
        """计算频率统计"""
        if self.stats['start_time'] and self.stats['end_time']:
            time_diff = self.stats['end_time'] - self.stats['start_time']
            minutes = time_diff.total_seconds() / 60
            
            if minutes == 0:
                return "N/A (时间跨度太短)"
            
            minutes_per_occurrence = minutes / count if count > 0 else 0
            hours_per_occurrence = minutes_per_occurrence / 60
            
            if minutes_per_occurrence >= 100:
                return f"每 {minutes_per_occurrence:.2f} 分钟一次 (约 {hours_per_occurrence:.2f} 小时一次)"
            else:
                return f"每 {minutes_per_occurrence:.2f} 分钟一次"
        return "N/A (未找到时间信息)"
    
    def _generate_report(self, vuid):
        """生成分析报告"""
        with open(f'{vuid}_mqtt_analysis_summary.md', 'w', encoding='utf-8') as f:
            f.write("# MQTT日志分析报告\n\n")
            f.write(f"生成时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n\n")
            
            # 添加统计时间范围
            if self.stats['start_time'] and self.stats['end_time']:
                f.write(f"统计时间范围: {self.stats['start_time'].strftime('%Y-%m-%d %H:%M:%S')} 至 "
                       f"{self.stats['end_time'].strftime('%Y-%m-%d %H:%M:%S')}\n\n")
            
            # Topic类型统计
            f.write("## Topic类型统计\n\n")
            
            # 输出各类型统计
            type_display = {
                'ntp': 'NTP校时',
                'shadow': '影子系统',
                'upgrade': '升级',
                'bind': '绑定状态',
                'address': '地址切换',
                'other': '其他消息'
            }
            
            for type_name, display_name in type_display.items():
                counter = self.stats['topic_types'][type_name]
                if counter:
                    f.write(f"### {display_name}\n")
                    for topic, count in sorted(counter.items()):
                        frequency = self._calculate_frequency(count)
                        f.write(f"- {topic}: {count}次 ({frequency})\n")
                    f.write("\n")
            
            # MQTT操作统计
            f.write("\n## MQTT操作统计\n\n")
            
            # 按操作类型分组
            operation_groups = {
                '心跳包': ['PINGREQ', 'PINGRESP'],
                '发布消息': ['PUBLISH', 'PUBACK', 'PUBREC', 'PUBREL', 'PUBCOMP'],
                '订阅消息': ['SUBSCRIBE', 'SUBACK'],
                '连接消息': ['CONNECT', 'CONNACK', 'DISCONNECT']
            }
            
            # 输出各组统计
            for group_name, operations in operation_groups.items():
                has_data = False
                f.write(f"### {group_name}\n")
                for op in operations:
                    count = self.stats['mqtt_operations'][op]
                    if count > 0:
                        has_data = True
                        frequency = self._calculate_frequency(count)
                        f.write(f"- {op}: {count}次 ({frequency})\n")
                if has_data:
                    f.write("\n")


def main(vuid_dic, start_date_str=None, end_date_str=None):
    """主函数"""
    for vuid in vuid_dic:
        log_file = r"E:\MQTT日志\9周\{}.log".format(vuid)
        vuid = log_file.split('\\')[-1].split('.')[0]
        analyzer = MQTTLogAnalyzer()
        analyzer.analyze_log(log_file, start_date_str, end_date_str)
        analyzer._generate_report(vuid)
    print("分析完成！请查看生成的报告文件：mqtt_analysis_summary.md")


if __name__ == "__main__":
    
    vuid_dic = {
        "VE2311189SXBQ": "VE2311189SXBQ",
        "VE2310821BWOW": "VE2310821BWOW",
        "VE2311277MMKB": "VE2311277MMKB",
        "VN0000129ZZDI": "VN0000129ZZDI"
    }
    main(vuid_dic, "2025-05-10", "2025-05-10")
    print("分析完成！请查看生成的报告文件：mqtt_analysis_summary.md")